package com.flute.haflute.jobbox.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 调度类线程的基类 封装调度细节 继承该类必须实现
 * 
 * 1. setupEnvironment：在任务开始调度前必须初始化运行环境
 * 
 * 2. execute：任务每次调度执行的代码
 * 
 */
public abstract class ScheduleBase {

	private static Logger logger = LoggerFactory.getLogger(ScheduleBase.class);

	/** 是否关闭标识 */
	boolean bShutdownFlag = false;

	/** 调度的时间间隔 */
	protected long checkInterval = 1000L;

	/** 后台线程名 */
	String backendName = "IMGScheduleBase";

	/** 内部真正进行调度的线程，对外屏蔽 */
	private ScheduledThread scheduledThread = null;

	public ScheduleBase() {
		setupEnvironment();
		scheduledThread = new ScheduledThread();
		startDaemonThread();
	}

	public ScheduleBase(long t) {
		checkInterval = t;
		setupEnvironment();
		scheduledThread = new ScheduledThread();
		startDaemonThread();
	}

	public ScheduleBase(long t, String name, boolean isDaemon) {
		checkInterval = t;
		backendName = name;
		setupEnvironment();
		scheduledThread = new ScheduledThread();
		scheduledThread.setDaemon(isDaemon);
		startDaemonThread();
	}

	public ScheduleBase(String name, boolean isDaemon) {
		backendName = name;
		setupEnvironment();
		scheduledThread = new ScheduledThread();
		scheduledThread.setDaemon(isDaemon);
		startDaemonThread();
	}

	private void startDaemonThread() {
		scheduledThread.start();
	}

	public void close() {
		bShutdownFlag = true;
	}

	/**
	 * 在任务开始调度前必须初始化运行环境
	 */
	protected abstract void setupEnvironment();

	/**
	 * 任务每次调度执行的代码
	 */
	protected abstract void execute();

	/**
	 * 调度线程
	 * 
	 */
	class ScheduledThread extends Thread {

		public ScheduledThread() {
			super(backendName);
		}

		public void run() {
			while (!bShutdownFlag) {
				try {
					execute();
					schedule();
				} catch (Exception err) {
					logger.error("run() one execute round", err);
				}
			}
		}

		/** 一次调度等待一定时间 */
		void schedule() {
			try {
				Thread.sleep(checkInterval);
			} catch (Exception err) {
				err.printStackTrace();
			}
		}
	}
}
